package util;

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 简单的Markdown解析器，用于在Swing组件中显示格式化文本
 */
public class MarkdownParser {

    /**
     * 将Markdown文本转换为富文本并应用到JTextPane
     */
    public static void applyMarkdownToTextPane(JTextPane textPane, String markdown) {
        StyledDocument doc = textPane.getStyledDocument();

        try {
            // 清空文档
            doc.remove(0, doc.getLength());

            // 创建样式
            Style defaultStyle = textPane.addStyle("default", null);
            StyleConstants.setFontFamily(defaultStyle, "Microsoft YaHei");
            StyleConstants.setFontSize(defaultStyle, 14);
            StyleConstants.setForeground(defaultStyle, new Color(55, 65, 81));

            Style boldStyle = textPane.addStyle("bold", defaultStyle);
            StyleConstants.setBold(boldStyle, true);

            Style italicStyle = textPane.addStyle("italic", defaultStyle);
            StyleConstants.setItalic(italicStyle, true);

            Style codeStyle = textPane.addStyle("code", defaultStyle);
            StyleConstants.setFontFamily(codeStyle, "Consolas");
            StyleConstants.setBackground(codeStyle, new Color(248, 250, 252));
            StyleConstants.setForeground(codeStyle, new Color(239, 68, 68));

            Style headingStyle = textPane.addStyle("heading", defaultStyle);
            StyleConstants.setBold(headingStyle, true);
            StyleConstants.setFontSize(headingStyle, 18);
            StyleConstants.setForeground(headingStyle, new Color(31, 41, 55));

            Style listStyle = textPane.addStyle("list", defaultStyle);
            StyleConstants.setLeftIndent(listStyle, 20);

            // 解析并应用样式
            parseAndApplyMarkdown(doc, markdown, defaultStyle, boldStyle, italicStyle,
                    codeStyle, headingStyle, listStyle);

        } catch (BadLocationException e) {
            // 如果解析失败，显示原始文本
            try {
                doc.insertString(0, markdown, textPane.getStyle("default"));
            } catch (BadLocationException ex) {
                // 静默处理
            }
        }
    }

    /**
     * 解析Markdown并应用样式
     */
    private static void parseAndApplyMarkdown(StyledDocument doc, String markdown,
            Style defaultStyle, Style boldStyle, Style italicStyle,
            Style codeStyle, Style headingStyle, Style listStyle)
            throws BadLocationException {
        String[] lines = markdown.split("\n");
        boolean inCodeBlock = false;

        // 创建表格样式
        Style tableHeaderStyle = doc.addStyle("tableHeader", defaultStyle);
        StyleConstants.setBold(tableHeaderStyle, true);
        StyleConstants.setBackground(tableHeaderStyle, new Color(243, 244, 246));
        StyleConstants.setForeground(tableHeaderStyle, new Color(31, 41, 55));

        Style tableCellStyle = doc.addStyle("tableCell", defaultStyle);
        StyleConstants.setBackground(tableCellStyle, new Color(249, 250, 251));

        Style tableBorderStyle = doc.addStyle("tableBorder", defaultStyle);
        StyleConstants.setForeground(tableBorderStyle, new Color(209, 213, 219));

        for (int i = 0; i < lines.length; i++) {
            String line = lines[i];

            // 处理代码块开始/结束
            if (line.trim().equals("```")) {
                inCodeBlock = !inCodeBlock;
                continue;
            }

            // 如果在代码块内，直接使用代码样式
            if (inCodeBlock) {
                doc.insertString(doc.getLength(), line + "\n", codeStyle);
                continue;
            }

            // 处理标题 (# ## ### ####)
            if (line.startsWith("#### ")) {
                Style h4Style = doc.addStyle("h4", headingStyle);
                StyleConstants.setFontSize(h4Style, 16);
                doc.insertString(doc.getLength(), line.substring(5).trim() + "\n", h4Style);
            } else if (line.startsWith("### ")) {
                Style h3Style = doc.addStyle("h3", headingStyle);
                StyleConstants.setFontSize(h3Style, 18);
                doc.insertString(doc.getLength(), line.substring(4).trim() + "\n", h3Style);
            } else if (line.startsWith("## ")) {
                Style h2Style = doc.addStyle("h2", headingStyle);
                StyleConstants.setFontSize(h2Style, 20);
                doc.insertString(doc.getLength(), line.substring(3).trim() + "\n", h2Style);
            } else if (line.startsWith("# ")) {
                Style h1Style = doc.addStyle("h1", headingStyle);
                StyleConstants.setFontSize(h1Style, 22);
                doc.insertString(doc.getLength(), line.substring(2).trim() + "\n", h1Style);
            }
            // 处理列表项 (• - * 开头)
            else if (line.trim().startsWith("• ") || line.trim().startsWith("- ") || line.trim().startsWith("* ")) {
                String content = line.trim().substring(2);
                doc.insertString(doc.getLength(), "• ", listStyle);
                parseInlineMarkdown(doc, content + "\n", defaultStyle, boldStyle, italicStyle, codeStyle);
            }
            // 处理数字列表
            else if (line.trim().matches("^\\d+\\.\\s+.*")) {
                parseInlineMarkdown(doc, line.trim() + "\n", listStyle, boldStyle, italicStyle, codeStyle);
            }
            // 处理分隔线 (--- 或 ***)
            else if (line.trim().equals("---") || line.trim().equals("***")) {
                Style separatorStyle = doc.addStyle("separator", defaultStyle);
                StyleConstants.setForeground(separatorStyle, new Color(209, 213, 219));
                doc.insertString(doc.getLength(), "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", separatorStyle);
            }
            // 处理表格
            else if (line.trim().startsWith("|") && line.trim().endsWith("|")) {
                i = parseTable(doc, lines, i, tableHeaderStyle, tableCellStyle, tableBorderStyle, defaultStyle);
            }
            // 处理普通文本行或空行
            else if (!line.trim().isEmpty()) {
                parseInlineMarkdown(doc, line + "\n", defaultStyle, boldStyle, italicStyle, codeStyle);
            } else {
                doc.insertString(doc.getLength(), "\n", defaultStyle);
            }
        }
    }

    /**
     * 解析行内Markdown（粗体、斜体、行内代码）
     */
    private static void parseInlineMarkdown(StyledDocument doc, String text,
            Style defaultStyle, Style boldStyle,
            Style italicStyle, Style codeStyle) throws BadLocationException {

        // 创建一个包含所有需要处理的模式的数组
        Pattern[] patterns = {
                Pattern.compile("`([^`]+)`"), // 行内代码
                Pattern.compile("\\*\\*([^*]+?)\\*\\*"), // 粗体
                Pattern.compile("\\*([^*]+?)\\*") // 斜体（但不匹配粗体）
        };

        Style[] styles = { codeStyle, boldStyle, italicStyle };

        // 找到所有匹配项及其位置
        java.util.List<MatchInfo> matches = new java.util.ArrayList<>();

        for (int i = 0; i < patterns.length; i++) {
            Matcher matcher = patterns[i].matcher(text);
            while (matcher.find()) {
                // 排除粗体中的斜体匹配
                if (i == 2) { // 斜体模式
                    // 检查是否在粗体标记内
                    String before = text.substring(Math.max(0, matcher.start() - 2), matcher.start());
                    String after = text.substring(matcher.end(), Math.min(text.length(), matcher.end() + 2));
                    if (before.equals("**") || after.equals("**")) {
                        continue; // 跳过粗体内的斜体
                    }
                }
                matches.add(new MatchInfo(matcher.start(), matcher.end(), matcher.group(1), styles[i]));
            }
        }

        // 按开始位置排序
        matches.sort((a, b) -> Integer.compare(a.start, b.start));

        // 移除重叠的匹配项（优先级：代码 > 粗体 > 斜体）
        for (int i = matches.size() - 1; i > 0; i--) {
            MatchInfo current = matches.get(i);
            MatchInfo previous = matches.get(i - 1);
            if (current.start < previous.end) {
                matches.remove(i); // 移除重叠的匹配项
            }
        }

        // 应用格式
        int lastIndex = 0;
        for (MatchInfo match : matches) {
            // 插入匹配前的普通文本
            if (match.start > lastIndex) {
                doc.insertString(doc.getLength(), text.substring(lastIndex, match.start), defaultStyle);
            }
            // 插入格式化的文本
            doc.insertString(doc.getLength(), match.content, match.style);
            lastIndex = match.end;
        }

        // 插入剩余的普通文本
        if (lastIndex < text.length()) {
            doc.insertString(doc.getLength(), text.substring(lastIndex), defaultStyle);
        }
    }

    /**
     * 匹配信息辅助类
     */
    private static class MatchInfo {
        int start, end;
        String content;
        Style style;

        MatchInfo(int start, int end, String content, Style style) {
            this.start = start;
            this.end = end;
            this.content = content;
            this.style = style;
        }
    }

    /**
     * 简化版：将Markdown转换为HTML，用于JLabel等组件
     */
    public static String markdownToHtml(String markdown) {
        if (markdown == null || markdown.isEmpty()) {
            return "";
        }

        StringBuilder html = new StringBuilder("<html><body style='font-family: Microsoft YaHei; color: #374151;'>");

        String[] lines = markdown.split("\n");
        boolean inCodeBlock = false;

        for (String line : lines) {
            if (line.trim().equals("```")) {
                if (inCodeBlock) {
                    html.append("</code></pre>");
                } else {
                    html.append("<pre style='background-color: #f8fafc; padding: 8px; border-radius: 4px;'><code>");
                }
                inCodeBlock = !inCodeBlock;
                continue;
            }

            if (inCodeBlock) {
                html.append(escapeHtml(line)).append("\n");
                continue;
            }

            // 处理标题
            if (line.startsWith("### ")) {
                html.append("<h3>").append(escapeHtml(line.substring(4))).append("</h3>");
            } else if (line.startsWith("## ")) {
                html.append("<h2>").append(escapeHtml(line.substring(3))).append("</h2>");
            } else if (line.startsWith("# ")) {
                html.append("<h1>").append(escapeHtml(line.substring(2))).append("</h1>");
            }
            // 处理列表
            else if (line.trim().startsWith("• ") || line.trim().startsWith("- ") || line.trim().startsWith("* ")) {
                html.append("<li>").append(escapeHtml(line.trim().substring(2))).append("</li>");
            }
            // 处理数字列表
            else if (line.trim().matches("^\\d+\\.\\s+.*")) {
                html.append("<li>").append(escapeHtml(line.trim().replaceFirst("^\\d+\\.\\s+", ""))).append("</li>");
            }
            // 处理普通文本
            else if (!line.trim().isEmpty()) {
                String processedLine = processInlineMarkdownToHtml(line);
                html.append("<p>").append(processedLine).append("</p>");
            } else {
                html.append("<br>");
            }
        }

        html.append("</body></html>");
        return html.toString();
    }

    /**
     * 处理行内Markdown到HTML
     */
    private static String processInlineMarkdownToHtml(String text) {
        // 处理粗体 **text**
        text = text.replaceAll("\\*\\*([^*]+)\\*\\*", "<b>$1</b>");

        // 处理斜体 *text*
        text = text.replaceAll("\\*([^*]+)\\*", "<i>$1</i>");

        // 处理行内代码 `code`
        text = text.replaceAll("`([^`]+)`",
                "<code style='background-color: #f8fafc; color: #ef4444; padding: 2px 4px; border-radius: 3px;'>$1</code>");

        return escapeHtml(text);
    }

    /**
     * 解析Markdown表格
     */
    private static int parseTable(StyledDocument doc, String[] lines, int startIndex,
            Style tableHeaderStyle, Style tableCellStyle,
            Style tableBorderStyle, Style defaultStyle) throws BadLocationException {
        java.util.List<String[]> tableRows = new java.util.ArrayList<>();
        boolean hasHeaderSeparator = false;
        int currentIndex = startIndex;

        // 收集表格的所有行
        while (currentIndex < lines.length) {
            String line = lines[currentIndex];
            if (!line.trim().startsWith("|") || !line.trim().endsWith("|")) {
                break;
            }

            // 检查是否是分隔线 (|---|---|)
            if (line.trim().matches("\\|\\s*:?-+:?\\s*(\\|\\s*:?-+:?\\s*)*\\|")) {
                hasHeaderSeparator = true;
                currentIndex++;
                continue;
            }

            // 解析表格行
            String[] cells = parseTableRow(line);
            if (cells.length > 0) {
                tableRows.add(cells);
            }
            currentIndex++;
        }

        // 如果没有找到有效的表格数据，返回
        if (tableRows.isEmpty()) {
            return startIndex;
        }

        // 计算每列的最大宽度
        int maxCols = 0;
        for (String[] row : tableRows) {
            maxCols = Math.max(maxCols, row.length);
        }

        int[] colWidths = new int[maxCols];
        for (String[] row : tableRows) {
            for (int i = 0; i < row.length && i < maxCols; i++) {
                colWidths[i] = Math.max(colWidths[i], row[i].length());
            }
        }

        // 确保每列至少有最小宽度
        for (int i = 0; i < colWidths.length; i++) {
            colWidths[i] = Math.max(1, colWidths[i]);
        }

        // 渲染表格
        renderTable(doc, tableRows, colWidths, tableHeaderStyle, tableCellStyle,
                tableBorderStyle, hasHeaderSeparator);

        return currentIndex - 1; // 返回处理到的最后一行索引
    }

    /**
     * 解析表格行，提取单元格内容
     */
    private static String[] parseTableRow(String line) {
        // 移除首尾的 |，然后按 | 分割
        String content = line.trim();
        if (content.startsWith("|")) {
            content = content.substring(1);
        }
        if (content.endsWith("|")) {
            content = content.substring(0, content.length() - 1);
        }

        String[] cells = content.split("\\|");
        for (int i = 0; i < cells.length; i++) {
            cells[i] = cells[i].trim();
        }
        return cells;
    }

    /**
     * 渲染表格到文档
     */
    private static void renderTable(StyledDocument doc, java.util.List<String[]> tableRows,
            int[] colWidths, Style tableHeaderStyle, Style tableCellStyle,
            Style tableBorderStyle, boolean hasHeaderSeparator) throws BadLocationException {

        // 添加表格前的空行
        doc.insertString(doc.getLength(), "\n", tableBorderStyle);

        // 生成表格边框字符（确保最小宽度）
        StringBuilder topBorder = new StringBuilder("┌");
        for (int i = 0; i < colWidths.length; i++) {
            int width = Math.max(1, colWidths[i]);
            for (int j = 0; j < width + 2; j++) {
                topBorder.append("─");
            }
            if (i < colWidths.length - 1) {
                topBorder.append("┬");
            }
        }
        topBorder.append("┐\n");

        StringBuilder middleBorder = new StringBuilder("├");
        for (int i = 0; i < colWidths.length; i++) {
            int width = Math.max(1, colWidths[i]);
            for (int j = 0; j < width + 2; j++) {
                middleBorder.append("─");
            }
            if (i < colWidths.length - 1) {
                middleBorder.append("┼");
            }
        }
        middleBorder.append("┤\n");

        StringBuilder bottomBorder = new StringBuilder("└");
        for (int i = 0; i < colWidths.length; i++) {
            int width = Math.max(1, colWidths[i]);
            for (int j = 0; j < width + 2; j++) {
                bottomBorder.append("─");
            }
            if (i < colWidths.length - 1) {
                bottomBorder.append("┴");
            }
        }
        bottomBorder.append("┘\n");

        // 渲染顶部边框
        doc.insertString(doc.getLength(), topBorder.toString(), tableBorderStyle);

        // 渲染表格行
        for (int rowIndex = 0; rowIndex < tableRows.size(); rowIndex++) {
            String[] row = tableRows.get(rowIndex);

            // 确定使用的样式（第一行是表头，如果有分隔符的话）
            Style cellStyle = (rowIndex == 0 && hasHeaderSeparator) ? tableHeaderStyle : tableCellStyle;

            doc.insertString(doc.getLength(), "│", tableBorderStyle);

            for (int colIndex = 0; colIndex < colWidths.length; colIndex++) {
                String cellContent = (colIndex < row.length) ? row[colIndex] : "";

                // 填充到指定宽度（确保最小宽度为1，避免格式化错误）
                int width = Math.max(1, colWidths[colIndex]);
                String paddedContent = String.format(" %-" + width + "s ", cellContent);
                doc.insertString(doc.getLength(), paddedContent, cellStyle);
                doc.insertString(doc.getLength(), "│", tableBorderStyle);
            }

            doc.insertString(doc.getLength(), "\n", tableBorderStyle);

            // 在表头后添加中间边框
            if (rowIndex == 0 && hasHeaderSeparator && rowIndex < tableRows.size() - 1) {
                doc.insertString(doc.getLength(), middleBorder.toString(), tableBorderStyle);
            }
        }

        // 渲染底部边框
        doc.insertString(doc.getLength(), bottomBorder.toString(), tableBorderStyle);

        // 添加表格后的空行
        doc.insertString(doc.getLength(), "\n", tableBorderStyle);
    }

    /**
     * HTML转义
     */
    private static String escapeHtml(String text) {
        return text.replace("&", "&amp;")
                .replace("<", "&lt;")
                .replace(">", "&gt;")
                .replace("\"", "&quot;")
                .replace("'", "&#39;");
    }
}
